<!DOCTYPE html>
<html>
  <head lang="en">
    <meta charset="utf-8" />
    <meta name="viewport" content="width=device-width" />

    <title>Web Audio API examples: AudioContext object's states</title>
  </head>

  <body>
    <h1>Web Audio API examples: AudioContext object's states</h1>

    <button>Create context</button>
    <button>Suspend context</button>
    <button>Stop context</button>

    <p>Current context time: No context exists.</p>

    <script>
      let audioCtx;

      const startBtn = document.querySelector("button:nth-of-type(1)");
      const susresBtn = document.querySelector("button:nth-of-type(2)");
      const stopBtn = document.querySelector("button:nth-of-type(3)");

      const timeDisplay = document.querySelector("p");

      susresBtn.setAttribute("disabled", "disabled");
      stopBtn.setAttribute("disabled", "disabled");

      startBtn.onclick = () => {
        startBtn.setAttribute("disabled", "disabled");
        susresBtn.removeAttribute("disabled");
        stopBtn.removeAttribute("disabled");

        // Create web audio api context
        audioCtx = new AudioContext();

        // Create an Oscillator and a Gain node
        const oscillator = new OscillatorNode(audioCtx, {
          type: "square",
          frequency: 100, // Value in Herz
        });
        const gainNode = new GainNode(audioCtx, { gain: 0.1 });

        // Connect both nodes to the speakers

        oscillator.connect(gainNode);
        gainNode.connect(audioCtx.destination);

        // Now that everything is connected, starts the sound
        oscillator.start(0);

        // Report the state of the audio context to the
        // console, when it changes

        audioCtx.onstatechange = function () {
          console.log(audioCtx.state);
        };
      };

      // Suspend/resume the audiocontext
      susresBtn.onclick = () => {
        if (audioCtx.state === "running") {
          audioCtx.suspend().then(() => {
            susresBtn.textContent = "Resume context";
          });
        } else if (audioCtx.state === "suspended") {
          audioCtx.resume().then(() => {
            susresBtn.textContent = "Suspend context";
          });
        }
      };

      // Close the audiocontext
      stopBtn.onclick = () => {
        audioCtx.close().then(() => {
          startBtn.removeAttribute("disabled");
          susresBtn.setAttribute("disabled", "disabled");
          // Reset the text of the suspend/resume toggle:
          susresBtn.textContent = "Suspend context";
          stopBtn.setAttribute("disabled", "disabled");
        });
      };

      // Helper function
      function displayTime() {
        if (audioCtx && audioCtx.state !== "closed") {
          timeDisplay.textContent = `Current context time: ${audioCtx.currentTime.toFixed(
            3
          )}`;
        } else {
          timeDisplay.textContent = "Current context time: No context exists.";
        }
        requestAnimationFrame(displayTime);
      }

      displayTime();
    </script>
  </body>
</html>
